<template>
  <div class="file-upload-container">
    <BaseDialog
      width="1200px"
      :title="title"
      v-model:visible="innerVisible"
      :renderDefaultFooter="false"
    >
      <template #title-slot>
        <div>
          <el-alert
            :title="
              $t('温馨提示：文件全部上传成功就会关闭哦！0KB文件会上传失败！')
            "
            type="warning"
            :closable="false"
          />
        </div>
      </template>
      <div style="padding: 10px">
        <!-- 拖拽上传区域 -->
        <div class="upload-area">
          <el-upload
            class="upload-demo"
            drag
            :multiple="multiple"
            :limit="limit"
            :before-upload="beforeUpload"
            :on-change="handleChange"
            :auto-upload="false"
            :accept="accept"
            :show-file-list="false"
            :on-exceed="handleExceed"
            :file-list="dataSource"
          >
            <el-icon class="el-icon--upload"><UploadFilled /></el-icon>
            <div class="el-upload__text">
              {{ $t("点击或将文件拖拽到这里上传") }}
            </div>
          </el-upload>
        </div>

        <!-- 文件列表表格 -->
        <div class="file-table-wrapper">
          <MyTable
            tableId="fileUpload"
            :columns="columns"
            :dataSource="dataSource"
            :loading="loading"
            :keepSource="true"
            :edit-rules="editRules"
            :edit-config="{
              trigger: 'click',
              mode: 'row',
              showStatus: true,
              enabled: true,
            }"
            :columnMinWidth="150"
            :maxHeight="300"
            ref="fileTable"
            moduleName="fileUpload"
          >
          </MyTable>
        </div>

        <!-- 底部按钮 -->
        <div class="dialog-footer">
          <el-button @click="handleCancel">{{ $t("取消") }}</el-button>
          <el-button type="primary" @click="handleConfirm">{{
            !dataSourceType ? $t("确认") : $t("上传")
          }}</el-button>
        </div>
      </div>
    </BaseDialog>
  </div>
</template>

<script setup lang="tsx">
import { ref, computed, defineProps, defineEmits, onMounted, watch } from "vue";
import { ElMessage } from "element-plus";
import BaseDialog from "@/components/BaseDialog/index.vue";
import MyTable from "@/components/MyTable/index.vue";
import { UploadFilled } from "@element-plus/icons-vue";
import * as api from "@/api/index.js";
import i18n from "@/lang/index.js";
import { tabelColumnFilters, getSubZhEn, fileViewing } from "@/utils/mUtils.js";
// Props定义
const props = defineProps({
  title: {
    type: String,
    default: "文件上传",
  },
  visible: {
    type: Boolean,
    default: false,
  },
  multiple: {
    type: Boolean,
    default: true,
  },
  limit: {
    type: Number,
    default: 99, // 默认最大10MB
  },
  accept: {
    type: String,
    default: "*", // 默认接受所有文件
  },
  maxSize: {
    type: Number,
    default: 10, // 默认最大10MB
  },
  sourceNo: {
    type: String,
    default: "",
  },
  sourceNoList: {
    type: Array,
    deflault: [],
  },
  busTypeCode: {
    type: String,
    default: "015001",
  },
});

// Emits定义
const emits = defineEmits(["update:visible", "onConfirm", "onCancel"]);

// 内部状态
const innerVisible = computed({
  get() {
    return props.visible;
  },
  set(val) {
    emits("update:visible", val);
  },
});

const dataSource = ref([]);
const loading = ref(false);
const fileTable = ref(null);

const dataSourceType = computed(() => {
  return dataSource.value.filter((item) => item.status !== "2").length;
});
watch(
  () => dataSourceType.value,
  (val) => {
    if (!val) {
      innerVisible.value = false;
      emits("onConfirm", dataSource.value);
      return;
    }
  }
);
// 上传提示信息
const uploadTip = computed(() => {
  let tip = `支持 ${props.multiple ? "多文件" : "单文件"} 上传，`;
  tip += `最大文件大小 ${props.maxSize}MB`;
  if (props.accept !== "*") {
    tip += `，支持格式：${props.accept
      .replace(/\./g, "")
      .replace(/\|/g, "、")}`;
  }
  return tip;
});

// 表格列配置
const columns = ref([
  {
    field: "original",
    title: "文件名",
    editRender: {},
    slots: { edit: "input_edit" },
  },
  {
    field: "status",
    title: "上传状态",
    width: 120,
    slots: {
      default: ({ row }) => {
        const obj = {
          0: {
            label: i18n.global.t("待上传"),
            type: "info",
          },
          1: {
            label: i18n.global.t("上传中"),
            type: "warning",
          },
          2: {
            label: i18n.global.t("上传成功"),
            type: "success",
          },
          3: {
            label: i18n.global.t("上传失败"),
            type: "danger",
          },
        };
        return [
          <el-tag type={obj[row.status].type} effect="plain">
            {obj[row.status].label}
          </el-tag>,
          <el-button
            style="margin-left: 5px"
            type="primary"
            plain
            icon="View"
            circle
            size="small"
            onClick={() => openFileView(row)}
          />,
        ];
      },
    },
  },
  {
    field: "fileFormat",
    title: "文件格式",
    formatter: ({ cellValue }) => cellValue || "",
    width: 100,
  },
  {
    field: "busSubTypeCode",
    title: "文件类型",
    editRender: {},
    params: {
      options: [],
      change: (val, rowIndex, row, options) => {
        row.busSubTypeName = val.option.label;
      },
      key: "subName",
      value: "subCode",
      label: "subName",
      transfer: true,
    },
    slots: { edit: "select_edit" },
    formatter: ({ cellValue, row }) => {
      return row.busSubTypeName;
    },
  },
  {
    field: "validityTimeStart",
    title: "有效期起",
    editRender: {},
    slots: { edit: "datePick_edit" },
    formatter: ({ cellValue }) => cellValue || "",
  },
  {
    field: "validityTimeEnd",
    title: "有效期止",
    editRender: {},
    slots: { edit: "datePick_edit" },
    formatter: ({ cellValue }) => cellValue || "",
  },
  {
    field: "fileSize",
    title: "文件大小",
    formatter: ({ cellValue }) => cellValue || "",
    width: 100,
  },
  {
    field: "remark",
    title: "备注",
    editRender: {},
    slots: { edit: "input_edit" },
  },
  {
    title: "操作",
    field: "operation",
    width: 100,
    slots: { default: "operation_default" },
    fixed: "right",
    params: [
      {
        title: "删除",
        type: "danger",
        icon: "Delete",
        click: (row, bloo, index) => {
          if (row.id.includes("file_") && !row.fileId) {
            dataSource.value.splice(index, 1);
            ElMessage.success(i18n.global.t("删除成功"));
            return;
          }
          onDelete(row, bloo, index);
        },
      },
      {
        title: "重新上传",
        type: "success",
        icon: "RefreshRight",
        setDisabled: (row) => {
          return row.status !== "3";
        },
        click: (row, bloo, index) => {
          fileSave(row);
        },
      },
    ],
  },
]);

onMounted(() => {
  if (!props.sourceNo) {
    dataSource.value = [...props.sourceNoList];
  } else {
    getInfo();
  }
  onGetSub();
});
const getInfo = () => {
  api.default.system.fileUpload
    .list({
      sourceNo: props.sourceNo,
    })
    .then((res) => {
      dataSource.value = res.rows.map((item) => {
        return {
          ...item,
          status: "2",
        };
      });
    });
};
const onGetSub = () => {
  getSubZhEn({
    code: "016",
  }).then((res) => {
    tabelColumnFilters(columns.value, "busSubTypeCode").params.options =
      res["016"];
  });
};

// 编辑验证规则
const editRules = ref({
  original: [
    {
      required: true,
      message: "请输入文件名",
    },
  ],
  busSubTypeCode: [
    {
      required: true,
      message: "请选择文件类型",
    },
  ],
  validityTimeStart: [
    {
      validator({ row, cellValue }) {
        return new Promise((resolve, reject) => {
          setTimeout(() => {
            if (row.busSubTypeCode === "016001" && !cellValue) {
              reject(new Error("文件类型为合同时有效期起为必填项"));
            } else {
              resolve();
            }
          }, 0);
        });
      },
    },
  ],
  validityTimeEnd: [
    {
      validator({ row, cellValue }) {
        return new Promise((resolve, reject) => {
          setTimeout(() => {
            if (row.busSubTypeCode === "016001" && !cellValue) {
              reject(new Error("文件类型为合同时有效期止为必填项"));
            } else if (
              row.validityTimeStart &&
              cellValue &&
              cellValue < row.validityTimeStart
            ) {
              reject(new Error("有效期止不能早于有效期起"));
            } else {
              resolve();
            }
          }, 0);
        });
      },
    },
  ],
});
const handleExceed = (files, fileList) => {
  ElMessage.warning(
    `当前限制选择 ${props.limit} 个文件，本次选择了 ${files.length} 个文件！`
  );
};
// 文件上传前校验
const beforeUpload = (file) => {
  // 检查文件大小
  const isLtMaxSize = file.size / 1024 / 1024 < props.maxSize;
  if (!isLtMaxSize) {
    ElMessage.error(`文件大小不能超过 ${props.maxSize}MB`);
    return false;
  }

  // 检查文件类型（如果指定了accept）
  if (props.accept !== "*") {
    const fileExtension = file.name.split(".").pop().toLowerCase();
    const acceptExtensions = props.accept
      .split("|")
      .map((ext) => ext.replace(/\./g, "").toLowerCase());

    if (!acceptExtensions.includes(fileExtension)) {
      ElMessage.error(
        `不支持的文件类型，请上传 ${acceptExtensions.join("、")} 格式的文件`
      );
      return false;
    }
  }

  return true;
};

// 处理文件变化
const handleChange = (file, fileList) => {
  if (file.status === "ready") {
    // 检查文件数量是否超过限制
    // 创建文件记录
    const fileRecord = {
      id: `file_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
      original: file.name,
      fileFormat: file.name.split(".").pop().toLowerCase(),
      fileSize: formatFileSize(file.size),
      rawFile: file.raw, // 保存原始文件对象
      status: "0",
    };
    dataSource.value.push(fileRecord);
  }
};

// 格式化文件大小
const formatFileSize = (size) => {
  if (size < 1024) {
    return size + " B";
  } else if (size < 1024 * 1024) {
    return (size / 1024).toFixed(2) + " KB";
  } else {
    return (size / (1024 * 1024)).toFixed(2) + " MB";
  }
};

const onDelete = (row, bloo, index) => {
  api.default.system.fileUpload.remove(row.fileId || row.id).then((res) => {
    dataSource.value.splice(index, 1);
    ElMessage.success(i18n.global.t("删除成功"));
  });
};
// 处理确认
const handleConfirm = async () => {
  const valid = await fileTable.value.validEvent();
  if (valid) {
    let row = null;
    for (const key in valid) {
      row = valid[key][0].row;
      if (row) {
        break;
      }
    }
    const newRow = dataSource.value.find((item) => item.id === row.id);
    fileTable.value.$refs.xGrid.setEditCell(newRow, "original");
    return;
  }
  if (!dataSourceType.value) {
    innerVisible.value = false;
    emits("onConfirm", dataSource.value);
    return;
  }
  dataSource.value.forEach((item) => {
    if (item.status === "2") return;
    fileSave(item);
  });
};

const fileSave = (row) => {
  row.status = "1";
  const formData = new FormData();
  formData.append("file", row.rawFile);
  formData.append("sourceNo", props.sourceNo);
  formData.append("busTypeCode", props.busTypeCode);
  formData.append("busSubTypeCode", row.busSubTypeCode);
  formData.append("busSubTypeName", row.busSubTypeName);
  formData.append("validityTimeStart", row.validityTimeStart);
  formData.append("validityTimeEnd", row.validityTimeEnd);
  api.default.system.fileUpload
    .add(formData)
    .then((res) => {
      row.fileId = res.data.fileId;
      row.url = res.data.url;
      row.status = "2";
    })
    .catch((err) => {
      row.status = "3";
    });
};

// 处理取消
const handleCancel = () => {
  innerVisible.value = false;
  // 清空数据
  dataSource.value = [];
  emits("onCancel");
};

// 打开文件查看
const openFileView = (row) => {
  fileViewing(row.url, row.rawFile, row.original);
};

// 暴露方法给父组件
defineExpose({
  handleCancel,
  openFileView,
});
</script>

<style lang="scss" scoped>
.file-upload-container {
  width: 100%;
}

.upload-area {
  border: 1px dashed #dcdfe694;
  border-radius: 4px;
  margin-bottom: 20px;
  background-color: #fafafa;
}

.file-table-wrapper {
  margin-bottom: 20px;
}

.dialog-footer {
  text-align: right;
  padding: 20px;
  // border-top: 1px solid #ebeef5;
  // margin-top: 20px;
}

.dialog-footer :deep(.el-button) {
  margin-left: 10px;
}
.file-upload-container {
  :deep() .default-slot {
    height: auto !important;
  }
}
</style>